// hwinimaging.h

#pragma once
#ifndef __HWINIMAGING_H__
#define __HWINIMAGING_H__

#include "hwindef.h"
#include "hwincom.h"
#include "hwinexception.h"


namespace harlinn
{
    namespace windows
    {
        class Control;
        class BitmapHandle;

        namespace imaging
        {
            
#define HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL( classType, baseClassType , interfaceType, baseInterfaceType ) \
public: \
typedef interfaceType InterfaceType; \
typedef baseInterfaceType BaseInterfaceType; \
private: \
 InterfaceType * GetInterface() const { HWIN_TRACE(); if(!unknown) { ThrowNoInterface(); } return reinterpret_cast< InterfaceType *>( unknown ); } \
public: \
classType () \
 : baseClassType ( ) \
 {HWIN_TRACE();} \
explicit classType (interfaceType * theInterface, bool addref = false ) \
 : baseClassType ( reinterpret_cast< baseInterfaceType *>( theInterface ), addref ) \
 {HWIN_TRACE();} \
protected: \
classType (REFIID iid, const Unknown& theUnknown, bool throwIfNoInterface = true ) \
 : baseClassType ( iid, reinterpret_cast< const baseClassType & > (theUnknown), throwIfNoInterface ) \
 { HWIN_TRACE(); } \
public: \
classType ( const Unknown& theUnknown, bool throwIfNoInterface = true ) \
 : baseClassType ( __uuidof(interfaceType), reinterpret_cast< const baseClassType & > (theUnknown), throwIfNoInterface ) \
 { HWIN_TRACE(); } \
classType ( ImagingFactory* theFactory, interfaceType * theInterface ) \
 : baseClassType ( theFactory, reinterpret_cast< baseInterfaceType *>( theInterface ) ) \
 { HWIN_TRACE(); } \
classType (const classType & other) \
 : baseClassType ( reinterpret_cast< const baseClassType & > (other) ) \
 { HWIN_TRACE(); } \
classType (classType && other) \
 : baseClassType ( reinterpret_cast< baseClassType && >( other ) ) \
 { HWIN_TRACE(); } \
classType & operator = (const classType & other) \
 { \
   HWIN_TRACE(); \
   baseClassType :: operator = ( reinterpret_cast< const baseClassType & > (other) ); \
   return *this; \
 } \
classType & operator = (classType && other) \
 { \
   HWIN_TRACE(); \
   baseClassType :: operator = ( reinterpret_cast< baseClassType && > (other) ); \
   return *this; \
 } \
operator interfaceType * ( ) const\
 { \
   HWIN_TRACE(); \
   return reinterpret_cast< interfaceType * >( unknown ); \
 }


            typedef UINT32 Color;

            class Rectangle
            {
                INT x;
                INT y;
                INT width;
                INT height;
            public:
                Rectangle()
                    : x(0),y(0),width(0),height(0)
                {
                    HWIN_TRACE();
                }

                Rectangle(const POINT& pt)
                    : x(pt.x),y(pt.y),width(0),height(0)
                {
                    HWIN_TRACE();
                }

                Rectangle(const SIZE& size)
                    : x(0),y(0),width(size.cx),height(size.cy)
                {
                    HWIN_TRACE();
                }

                Rectangle(const POINT& pt, const SIZE& size)
                    : x(pt.x),y(pt.y),width(size.cx),height(size.cy)
                {
                    HWIN_TRACE();
                }

                int X() const 
                {
                    HWIN_TRACE();
                    return x;
                }
                Rectangle& SetX(int theValue) 
                {
                    HWIN_TRACE();
                    x=theValue;
                    return *this;
                }
                int Y() const 
                {
                    HWIN_TRACE();
                    return y;
                }
                Rectangle& SetY(int theValue) 
                {
                    HWIN_TRACE();
                    y=theValue;
                    return *this;
                }

                int Width() const 
                {
                    HWIN_TRACE();
                    return width;
                }
                Rectangle& SetWidth(int theWidth) 
                {
                    HWIN_TRACE();
                    width=theWidth;
                    return *this;
                }
                int Height() const 
                {
                    HWIN_TRACE();
                    return height;
                }
                Rectangle& SetHeight(int theValue) 
                {
                    HWIN_TRACE();
                    height=theValue;
                    return *this;
                }


                operator WICRect& () 
                { 
                    HWIN_TRACE();
                    return *((WICRect*)&x); 
                }
                operator const WICRect& () const 
                { 
                    HWIN_TRACE();
                    return *((WICRect*)&x); 
                }

                //operator WICRect* () { return ((WICRect*)&x); }
                operator WICRect* () const 
                { 
                    HWIN_TRACE();
                    return ((WICRect*)&x); 
                }
            };


            class Size
            {
                UINT width;
                UINT height;
            public:
                Size()
                    : width(0),height(0)
                {
                    HWIN_TRACE();
                }


                Size(UINT theWidth,UINT theHeight)
                    : width(theWidth),height(theHeight)
                {
                    HWIN_TRACE();
                }

                explicit Size(UINT theValue)
                    : width(theValue),height(theValue)
                {
                    HWIN_TRACE();
                }

                Size(const POINT& pt)
                    : width(UINT(pt.x)),height(UINT(pt.y))
                {
                    HWIN_TRACE();
                }

                Size(const SIZE& size)
                    : width(UINT(size.cx)),height(UINT(size.cy))
                {
                    HWIN_TRACE();
                }

                Size(const Size& size)
                    : width(size.width),height(size.height)
                {
                    HWIN_TRACE();
                }

                Size& operator = (const SIZE& size)
                {
                    HWIN_TRACE();
                    width = UINT(size.cx);
                    height = UINT(size.cy);
                    return *this;
                }

                Size& operator = (const POINT& pt)
                {
                    HWIN_TRACE();
                    width = UINT(pt.x);
                    height = UINT(pt.y);
                    return *this;
                }

                Size& operator = (const Size& size)
                {
                    HWIN_TRACE();
                    width = size.width;
                    height = size.height;
                    return *this;
                }


                UINT Width() const 
                {
                    HWIN_TRACE();
                    return width;
                }
                Size& SetWidth(UINT theWidth) 
                {
                    HWIN_TRACE();
                    width=theWidth;
                    return *this;
                }
                UINT Height() const 
                {
                    HWIN_TRACE();
                    return height;
                }
                Size& SetHeight(UINT theValue) 
                {
                    HWIN_TRACE();
                    height=theValue;
                    return *this;
                }
                Size& Set(UINT theWidth,UINT theHeight) 
                {
                    HWIN_TRACE();
                    width=theWidth;
                    height=theHeight;
                    return *this;
                }

            };


            class Resolution
            {
                double dpiX; 
                double dpiY;
            public:
                Resolution()
                    : dpiX(0.0),dpiY(0.0)
                {
                    HWIN_TRACE();
                }

                Resolution(double x, double y)
                    : dpiX(x),dpiY(y)
                {
                    HWIN_TRACE();
                }

                double X() const 
                {
                    HWIN_TRACE();
                    return dpiX;
                }
                Resolution& SetX(double theValue) 
                {
                    HWIN_TRACE();
                    dpiX=theValue;
                    return *this;
                }
                double Y() const 
                {
                    HWIN_TRACE();
                    return dpiY;
                }
                Resolution& SetY(double theValue) 
                {
                    HWIN_TRACE();
                    dpiY=theValue;
                    return *this;
                }
                Resolution& Set(double theXValue,double theYValue) 
                {
                    HWIN_TRACE();
                    dpiX=theXValue;
                    dpiY=theYValue;
                    return *this;
                }

            };


            enum class ColorContextType
            {
                Uninitialized	= 0,
                Profile	        = 0x1,
                ExifColorSpace	= 0x2
            };

            enum class BitmapCreateCacheOption : DWORD
            {
                NoCache	= 0,
                CacheOnDemand	= 0x1,
                CacheOnLoad	= 0x2
            };

            enum class DecodeOptions : DWORD
            {
                CacheOnDemand	= 0,
                CacheOnLoad	= 0x1
            };

            enum class BitmapEncoderCacheOption : DWORD
            {
                InMemory	= 0,
                TempFile	= 0x1,
                NoCache	= 0x2
            };

            enum class ComponentType : DWORD
            {
                Decoder	= 0x1,
                Encoder	= 0x2,
                PixelFormatConverter	= 0x4,
                MetadataReader	= 0x8,
                MetadataWriter	= 0x10,
                PixelFormat	= 0x20,
                AllComponents	= 0x3f
            };

            enum class ComponentEnumerateOptions : DWORD
            {
                Default	= 0,
                Refresh	= 0x1,
                Disabled	= 0x80000000,
                Unsigned	= 0x40000000,
                BuiltInOnly	= 0x20000000
            };


            struct BitmapPattern
            {
                unsigned long long Position;
                unsigned long Length;
                BYTE *Pattern;
                BYTE *Mask;
                BOOL EndOfStream;
            };

            enum class BitmapInterpolationMode : DWORD
            {
                NearestNeighbor	= 0,
                Linear	= 0x1,
                Cubic	= 0x2,
                Fant	= 0x3
            };

            enum class BitmapPaletteType : DWORD
            {
                Custom	= 0,
                MedianCut	= 0x1,
                FixedBW	= 0x2,
                FixedHalftone8	= 0x3,
                FixedHalftone27	= 0x4,
                FixedHalftone64	= 0x5,
                FixedHalftone125	= 0x6,
                FixedHalftone216	= 0x7,
                FixedWebPalette	= WICBitmapPaletteTypeFixedHalftone216,
                FixedHalftone252	= 0x8,
                FixedHalftone256	= 0x9,
                FixedGray4	= 0xa,
                FixedGray16	= 0xb,
                FixedGray256	= 0xc
            };


            enum class BitmapDitherType : DWORD
            {
                None	= 0,
                Solid	= 0,
                Ordered4x4	= 0x1,
                Ordered8x8	= 0x2,
                Ordered16x16	= 0x3,
                Spiral4x4	= 0x4,
                Spiral8x8	= 0x5,
                DualSpiral4x4	= 0x6,
                DualSpiral8x8	= 0x7,
                ErrorDiffusion	= 0x8
            };

            enum class BitmapAlphaChannelOption : DWORD
            {
                UseAlpha	= 0,
                UsePremultipliedAlpha	= 0x1,
                IgnoreAlpha	= 0x2
            };

            enum class BitmapTransformOptions : DWORD
            {
                Rotate0	= 0,
                Rotate90	= 0x1,
                Rotate180	= 0x2,
                Rotate270	= 0x3,
                FlipHorizontal	= 0x8,
                FlipVertical	= 0x10
            };

            enum class BitmapLockFlags : DWORD
            {
                Read	= 0x1,
                Write	= 0x2,
            };

            enum class BitmapDecoderCapabilities : DWORD
            {
                SameEncoder	= 0x1,
                CanDecodeAllImages	= 0x2,
                CanDecodeSomeImages	= 0x4,
                CanEnumerateMetadata	= 0x8,
                CanDecodeThumbnail	= 0x10
            };

            enum class ProgressOperation : DWORD
            {
                WICProgressOperationCopyPixels	= 0x1,
                WICProgressOperationWritePixels	= 0x2,
                WICProgressOperationAll	= 0xffff
            };

            enum class WICProgressNotification : DWORD
            {
                Begin	= 0x10000,
                End	= 0x20000,
                Frequent	= 0x40000,
                All	= 0xffff0000
            };

            enum class ComponentSigning : DWORD
            {
                Signed	= 0x1,
                Unsigned	= 0x2,
                Safe	= 0x4,
                Disabled	= 0x80000000
            };

            enum class GifLogicalScreenDescriptorProperties : DWORD
            {
                Signature	= 0x1,
                Width	= 0x2,
                Height	= 0x3,
                GlobalColorTableFlag	= 0x4,
                ColorResolution	= 0x5,
                SortFlag	= 0x6,
                GlobalColorTableSize	= 0x7,
                BackgroundColorIndex	= 0x8,
                PixelAspectRatio	= 0x9
            };

            enum class GifImageDescriptorProperties : DWORD
            {
                Left	= 0x1,
                Top	= 0x2,
                Width	= 0x3,
                Height	= 0x4,
                LocalColorTableFlag	= 0x5,
                InterlaceFlag	= 0x6,
                SortFlag	= 0x7,
                LocalColorTableSize	= 0x8
            };

            enum class GifGraphicControlExtensionProperties : DWORD
            {
                Disposal	= 0x1,
                UserInputFlag	= 0x2,
                TransparencyFlag	= 0x3,
                Delay	= 0x4,
                TransparentColorIndex	= 0x5
            };

            enum class GifApplicationExtensionProperties : DWORD
            {
                Application	= 0x1,
                Data	= 0x2
            };

            enum class GifCommentExtensionProperties : DWORD
            {
                Text	= 0x1
            };

            enum class JpegCommentProperties : DWORD
            {
                Text	= 0x1
            };

            enum class JpegLuminanceProperties : DWORD
            {
                Table	= 0x1
            };

            enum class JpegChrominanceProperties : DWORD
            {
                Table	= 0x1
            };

            enum class EightBIMIptcProperties : DWORD
            {
                PString	= 0,
                EmbeddedIPTC	= 0x1,
            };

            enum class EightBIMResolutionInfoProperties : DWORD
            {
                PString	= 0x1,
                HResolution	= 0x2,
                HResolutionUnit	= 0x3,
                WidthUnit	= 0x4,
                VResolution	= 0x5,
                VResolutionUnit	= 0x6,
                HeightUnit	= 0x7,
            };

            enum class EightBIMIptcDigestProperties : DWORD
            {
                PString	= 0x1,
                IptcDigest	= 0x2
            };

            enum class PngGamaProperties : DWORD
            {
                Gamma	= 0x1
            };

            enum class PngBkgdProperties : DWORD
            {
                BackgroundColor	= 0x1
            };

            enum class PngItxtProperties : DWORD
            {
                Keyword	= 0x1,
                CompressionFlag	= 0x2,
                LanguageTag	= 0x3,
                TranslatedKeyword	= 0x4,
                Text	= 0x5
            };

            enum class PngChrmProperties : DWORD
            {
                WhitePointX	= 0x1,
                WhitePointY	= 0x2,
                RedX	= 0x3,
                RedY	= 0x4,
                GreenX	= 0x5,
                GreenY	= 0x6,
                BlueX	= 0x7,
                BlueY	= 0x8
            };

            enum class PngHistProperties : DWORD
            {
                Frequencies	= 0x1
            };

            enum class PngIccpProperties : DWORD
            {
                ProfileName	= 0x1,
                ProfileData	= 0x2
            };

            enum class PngSrgbProperties : DWORD
            {
                RenderingIntent	= 0x1
            };

            enum class PngTimeProperties : DWORD
            {
                Year	= 0x1,
                Month	= 0x2,
                Day	= 0x3,
                Hour	= 0x4,
                Minute	= 0x5,
                Second	= 0x6
            };

            enum class SectionAccessLevel : DWORD
            {
                Read	= 0x1,
                ReadWrite	= 0x3
            };

            enum class PixelFormatNumericRepresentation : DWORD
            {
                Unspecified	= 0,
                Indexed	= 0x1,
                UnsignedInteger	= 0x2,
                SignedInteger	= 0x3,
                Fixed	= 0x4,
                Float	= 0x5
            };

            struct ImageParameters
            {
                D2D1_PIXEL_FORMAT PixelFormat;
                FLOAT DpiX;
                FLOAT DpiY;
                FLOAT Top;
                FLOAT Left;
                UINT32 PixelWidth;
                UINT32 PixelHeight;
            };

            class BitmapSource;
            class ImagingFactory;
            class ImagingObject : public Unknown
            {
                ImagingFactory* factory;
            protected:
                ImagingFactory* Factory() const
                {
                    HWIN_TRACE();
                    return factory;
                }
            public:
                typedef Unknown Base;

                ImagingObject() 
                    : Base( ),
                      factory(nullptr)
                {
                    HWIN_TRACE();
                } 
                explicit ImagingObject( IUnknown * theInterface, bool addref = false )
                    : Base( reinterpret_cast< IUnknown *>( theInterface ), addref ), 
                      factory(nullptr)
                {
                    HWIN_TRACE();
                } 

                ImagingObject( ImagingFactory* theFactory, IUnknown * theInterface )
                    : Base( reinterpret_cast< IUnknown *>( theInterface ) ), 
                      factory(theFactory)
                {
                    HWIN_TRACE();
                }
            protected:
                ImagingObject (REFIID iid, const Unknown& theUnknown, bool throwIfNoInterface = true ) 
                 : Base ( iid, theUnknown, throwIfNoInterface ) 
                 { HWIN_TRACE(); } 
            public:
                ImagingObject(const ImagingObject& other) 
                    : Base( reinterpret_cast< const Base& > (other) ),
                      factory(other.factory) 
                {
                    HWIN_TRACE();
                } 
                ImagingObject(ImagingObject&& other) 
                    : Base( reinterpret_cast< Base&& >( other ) ),
                      factory(other.factory)
                { 
                    HWIN_TRACE();
                } 
                ImagingObject& operator = (const ImagingObject& other) 
                { 
                    HWIN_TRACE();
                    Base :: operator = ( reinterpret_cast< const Base& > (other) ); 
                    factory = other.factory;
                    return *this; 
                } 
                ImagingObject& operator = (ImagingObject&& other) 
                { 
                    HWIN_TRACE();
                    Base :: operator = ( reinterpret_cast< Base&& > (other) ); 
                    factory = other.factory;
                    return *this; 
                } 

                

            };


            class Palette : public ImagingObject
            {
            public:
                typedef ImagingObject Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(Palette,ImagingObject,IWICPalette,IUnknown)

                HWIN_EXPORT Palette& InitializePredefined( BitmapPaletteType ePaletteType, bool addTransparentColor);
        
                HWIN_EXPORT Palette& InitializeCustom( Color *pColors, UINT cCount);
                HWIN_EXPORT Palette& InitializeCustom( const std::vector< Color >& theColors);
                HWIN_EXPORT Palette& InitializeCustom( std::shared_ptr<const std::vector< Color >>& theColors);
        
                HWIN_EXPORT Palette& InitializeFromBitmap( const BitmapSource& theSurface, UINT cCount, bool addTransparentColor);
        
                HWIN_EXPORT Palette& InitializeFromPalette(const Palette& thePalette);
        
                HWIN_EXPORT BitmapPaletteType Type( ) const;
        
                HWIN_EXPORT UINT GetColorCount( ) const;
        
                HWIN_EXPORT std::shared_ptr<std::vector< Color > > Colors( ) const;
        
                HWIN_EXPORT bool IsBlackWhite( ) const;
                HWIN_EXPORT bool IsGrayscale( ) const;
                HWIN_EXPORT bool HasAlpha( ) const;
            };


            class FormatConverter;
            class BitmapScaler;
            class BitmapClipper;
            class BitmapFlipRotator;
            class ColorTransform;
            class Bitmap;

            class BitmapSource : public ImagingObject
            {
            public:
                typedef ImagingObject Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(BitmapSource,ImagingObject,IWICBitmapSource,IUnknown)

                HWIN_EXPORT const BitmapSource& GetSize(UINT *puiWidth,UINT *puiHeight) const;
                HWIN_EXPORT Size GetSize( ) const;
                HWIN_EXPORT const BitmapSource& GetPixelFormat( WICPixelFormatGUID *pPixelFormat) const;
                HWIN_EXPORT WICPixelFormatGUID GetPixelFormat( ) const;
                HWIN_EXPORT const BitmapSource& GetResolution( double *pDpiX, double *pDpiY) const;
                HWIN_EXPORT Resolution GetResolution( ) const;
        
                HWIN_EXPORT const BitmapSource& CopyPalette(Palette& theTargetPalette) const;
                HWIN_EXPORT Palette CopyPalette( ) const;

        
                HWIN_EXPORT const BitmapSource& CopyPixels( Rectangle& rectangle, UINT bytePerStride, UINT bufferSize, BYTE *pbBuffer) const;
                HWIN_EXPORT const BitmapSource& CopyPixels( UINT bytePerStride, UINT bufferSize, BYTE *pbBuffer) const;

                HWIN_EXPORT FormatConverter Convert(REFGUID dstFormat, BitmapDitherType dither, const Palette& thePalette, double alphaThresholdPercent, BitmapPaletteType paletteTranslate) const;
                HWIN_EXPORT FormatConverter Convert(REFGUID dstFormat) const;
                HWIN_EXPORT FormatConverter Convert() const;
                HWIN_EXPORT BitmapScaler Scale(UINT uiWidth, UINT uiHeight, BitmapInterpolationMode mode = BitmapInterpolationMode::Fant) const;
                HWIN_EXPORT BitmapScaler Scale(const Size& size, BitmapInterpolationMode mode = BitmapInterpolationMode::Fant) const;
                HWIN_EXPORT BitmapClipper Clip(const Rectangle& reactangle) const;
                HWIN_EXPORT BitmapFlipRotator Rotate(BitmapTransformOptions options) const;
                HWIN_EXPORT Bitmap ToBitmap() const;
                
                HWIN_EXPORT std::shared_ptr<BitmapHandle> AsBitmapHandle() const;

        
            };

            class FormatConverter : public BitmapSource
            {
            public:
                typedef BitmapSource Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(FormatConverter,BitmapSource,IWICFormatConverter,IWICBitmapSource)

                HWIN_EXPORT FormatConverter& Initialize(const BitmapSource& theSource, REFGUID dstFormat, BitmapDitherType dither, const Palette& thePalette, double alphaThresholdPercent, BitmapPaletteType paletteTranslate);
                HWIN_EXPORT FormatConverter& Initialize(const BitmapSource& theSource, REFGUID dstFormat, double alphaThresholdPercent, BitmapPaletteType paletteTranslate);
        
                HWIN_EXPORT bool CanConvert( REFGUID  srcPixelFormat,REFGUID  dstPixelFormat) const;
        
            };

            class BitmapScaler : public BitmapSource
            {
            public:
                typedef BitmapSource Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(BitmapScaler,BitmapSource,IWICBitmapScaler,IWICBitmapSource)

                HWIN_EXPORT BitmapScaler& Initialize( const BitmapSource& theSource, UINT uiWidth, UINT uiHeight, BitmapInterpolationMode mode = BitmapInterpolationMode::Fant);
                HWIN_EXPORT BitmapScaler& Initialize( const BitmapSource& theSource, const Size& theSize, BitmapInterpolationMode mode = BitmapInterpolationMode::Fant);
            };


            class BitmapClipper : public BitmapSource
            {
            public:
                typedef BitmapSource Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(BitmapClipper,BitmapSource,IWICBitmapClipper,IWICBitmapSource)

                HWIN_EXPORT BitmapClipper& Initialize( const BitmapSource& theSource, const Rectangle& reactangle);
        
            };

            class BitmapFlipRotator : public BitmapSource
            {
            public:
                typedef BitmapSource Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(BitmapFlipRotator,BitmapSource,IWICBitmapFlipRotator,IWICBitmapSource)

                HWIN_EXPORT BitmapFlipRotator& Initialize( const BitmapSource& theSource, BitmapTransformOptions options );
        
            };

            class BitmapLock : public ImagingObject
            {
            public:
                typedef ImagingObject Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(BitmapLock,ImagingObject,IWICBitmapLock,IUnknown)

                HWIN_EXPORT const BitmapLock& GetSize( UINT *puiWidth, UINT *puiHeight) const;
                HWIN_EXPORT Size GetSize( ) const;
        
                HWIN_EXPORT const BitmapLock& GetStride( UINT *pcbStride) const;
                HWIN_EXPORT UINT GetStride( ) const;
        
                HWIN_EXPORT const BitmapLock& GetDataPointer( UINT *pcbBufferSize, BYTE **ppbData) const;
        
                HWIN_EXPORT const BitmapLock& GetPixelFormat( GUID *pPixelFormat) const;
                HWIN_EXPORT GUID GetPixelFormat( ) const;
        
            };

            class Bitmap : public BitmapSource
            {
            public:
                typedef BitmapSource Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(Bitmap,BitmapSource,IWICBitmap,IWICBitmapSource)

                HWIN_EXPORT BitmapLock Lock( const Rectangle& lockRectangle, DWORD flags);
                HWIN_EXPORT Bitmap& SetPalette( const Palette& thePalette);
                HWIN_EXPORT Bitmap& SetResolution( double dpiX, double dpiY);
                HWIN_EXPORT Bitmap& SetResolution( const Resolution& resolution);
        
            };


            class ColorContext : public ImagingObject
            {
            public:
                typedef ImagingObject Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(ColorContext,ImagingObject,IWICColorContext,IUnknown)

                HWIN_EXPORT ColorContext& InitializeFromFilename( LPCWSTR theFilename );
                HWIN_EXPORT ColorContext& InitializeFromFilename( const String& theFilename );
        
                HWIN_EXPORT ColorContext& InitializeFromMemory( const BYTE *theBuffer, UINT theBufferSize);
        
                HWIN_EXPORT ColorContext& InitializeFromExifColorSpace( UINT value);
        
                HWIN_EXPORT ColorContextType GetType( ) const;
        
                HWIN_EXPORT const ColorContext& GetProfileBytes( UINT bufferSize, BYTE *pbBuffer, UINT *actualNumberOfBytesCopied) const;
        
                HWIN_EXPORT UINT GetExifColorSpace( ) const;
        
            };


            class ColorTransform : public BitmapSource
            {
            public:
                typedef BitmapSource Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(ColorTransform,BitmapSource,IWICColorTransform,IWICBitmapSource)

                HWIN_EXPORT ColorTransform& Initialize( const BitmapSource& theBitmapSource, const ColorContext& theContextSource, const ColorContext& theContextDest, REFGUID pixelFmtDest);
        
            };


            class MetadataQueryWriter;
            class FastMetadataEncoder : public ImagingObject
            {
            public:
                typedef ImagingObject Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(FastMetadataEncoder,ImagingObject,IWICFastMetadataEncoder,IUnknown)

                HWIN_EXPORT FastMetadataEncoder& Commit( );
                HWIN_EXPORT MetadataQueryWriter GetMetadataQueryWriter( );
        
            };


            class Stream : public ImagingObject /*IStream*/
            {
            public:
                typedef ImagingObject Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(Stream,ImagingObject,IWICStream,IUnknown)

                HWIN_EXPORT Stream& InitializeFromIStream(IStream *theStream);
                HWIN_EXPORT Stream& InitializeFromFilename( LPCWSTR theFileName, DWORD theDesiredAccess);
                HWIN_EXPORT Stream& InitializeFromMemory( BYTE* theBuffer, DWORD theBufferSize);
                HWIN_EXPORT Stream& InitializeFromIStreamRegion( IStream* theStream, unsigned long long theOffset,unsigned long long theMaxSize);
        
            };


            class EnumMetadataItem : public ImagingObject
            {
            public:
                typedef ImagingObject Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(EnumMetadataItem,ImagingObject,IWICEnumMetadataItem,IUnknown)

                HWIN_EXPORT bool Next( ULONG celt,
                    PROPVARIANT *rgeltSchema,
                    PROPVARIANT *rgeltId,
                    PROPVARIANT *rgeltValue,
                    ULONG *pceltFetched);
        
                HWIN_EXPORT EnumMetadataItem& Skip(ULONG celt);
                HWIN_EXPORT EnumMetadataItem& Reset( );
                HWIN_EXPORT EnumMetadataItem Clone( ) const;
            };


            class MetadataQueryReader : public ImagingObject
            {
            public:
                typedef ImagingObject Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(MetadataQueryReader,ImagingObject,IWICMetadataQueryReader,IUnknown)

                HWIN_EXPORT const MetadataQueryReader& GetContainerFormat(GUID *pguidContainerFormat) const;
                HWIN_EXPORT GUID GetContainerFormat( ) const;
        
                HWIN_EXPORT const MetadataQueryReader& GetLocation( UINT cchMaxLength,WCHAR *wzNamespace, UINT *pcchActualLength) const;
                HWIN_EXPORT String GetLocation( ) const;
        
                HWIN_EXPORT const MetadataQueryReader& GetMetadataByName( LPCWSTR wzName,PROPVARIANT *pvarValue) const;
                HWIN_EXPORT const MetadataQueryReader& GetMetadataByName( const String& theName,PROPVARIANT *pvarValue) const;

        
                HWIN_EXPORT EnumString GetEnumerator( ) const;
        
            };


            class MetadataQueryWriter : public MetadataQueryReader
            {
            public:
                typedef MetadataQueryReader Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(MetadataQueryWriter,MetadataQueryReader,IWICMetadataQueryWriter,IWICMetadataQueryReader)

                HWIN_EXPORT MetadataQueryWriter& SetMetadataByName( LPCWSTR wzName, const PROPVARIANT *pvarValue);
                HWIN_EXPORT MetadataQueryWriter& RemoveMetadataByName(LPCWSTR wzName);
            };


            class BitmapFrameEncode;
            class BitmapEncoderInfo;
            class BitmapEncoder : public ImagingObject
            {
            public:
                typedef ImagingObject Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(BitmapEncoder,ImagingObject,IWICBitmapEncoder,IUnknown)

                HWIN_EXPORT BitmapEncoder& Initialize(IStream* theStream, BitmapEncoderCacheOption cacheOption);
        
                HWIN_EXPORT const BitmapEncoder& GetContainerFormat(GUID *pguidContainerFormat) const;
                HWIN_EXPORT GUID GetContainerFormat( ) const;
        
                HWIN_EXPORT BitmapEncoderInfo GetEncoderInfo( ) const;
        
                HWIN_EXPORT BitmapEncoder& SetColorContexts( std::shared_ptr< std::vector<ColorContext> > colorContexts );
        
                HWIN_EXPORT BitmapEncoder& SetPalette( const Palette& thePalette );
        
                HWIN_EXPORT BitmapEncoder& SetThumbnail( const BitmapSource& theThumbnail);
        
                HWIN_EXPORT BitmapEncoder& SetPreview( const BitmapSource& thePreview);
        
                HWIN_EXPORT BitmapFrameEncode CreateNewFrame( IPropertyBag2 **ppIEncoderOptions);
                HWIN_EXPORT BitmapFrameEncode CreateNewFrame( );
        
                HWIN_EXPORT BitmapEncoder& Commit( );
        
                HWIN_EXPORT MetadataQueryWriter GetMetadataQueryWriter() const;
        
            };


            class BitmapFrameEncode : public ImagingObject
            {
            public:
                typedef ImagingObject Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(BitmapFrameEncode,ImagingObject,IWICBitmapFrameEncode,IUnknown)

                HWIN_EXPORT BitmapFrameEncode& Initialize( );
                HWIN_EXPORT BitmapFrameEncode& Initialize(IPropertyBag2 *pIEncoderOptions);
        
                HWIN_EXPORT BitmapFrameEncode& SetSize(UINT uiWidth,UINT uiHeight);
                HWIN_EXPORT BitmapFrameEncode& SetSize(const Size& size);
        
                HWIN_EXPORT BitmapFrameEncode& SetResolution(double dpiX, double dpiY);
                HWIN_EXPORT BitmapFrameEncode& SetResolution(const Resolution& resolution);
        
                HWIN_EXPORT BitmapFrameEncode& SetPixelFormat( GUID *pPixelFormat);
                HWIN_EXPORT BitmapFrameEncode& SetPixelFormat( const GUID& thePixelFormat);
        
                HWIN_EXPORT BitmapFrameEncode& SetColorContexts( std::shared_ptr< std::vector<ColorContext> > colorContexts );
        
                HWIN_EXPORT BitmapFrameEncode& SetPalette(const Palette& thePalette);
        
                HWIN_EXPORT BitmapFrameEncode& SetThumbnail( const BitmapSource& theThumbnail );
        
                HWIN_EXPORT BitmapFrameEncode& WritePixels(UINT lineCount, UINT cbStride, UINT cbBufferSize, BYTE *pbPixels);
        
                HWIN_EXPORT BitmapFrameEncode& WriteSource( const BitmapSource& theBitmapSource, const Rectangle& rectangle);
                HWIN_EXPORT BitmapFrameEncode& WriteSource( const BitmapSource& theBitmapSource);
        
                HWIN_EXPORT BitmapFrameEncode& Commit( );
        
                HWIN_EXPORT MetadataQueryWriter GetMetadataQueryWriter( ) const;
        
            };

            class ImageEncoder : public ImagingObject
            {
            public:
                typedef ImagingObject Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(ImageEncoder,ImagingObject,IWICImageEncoder,IUnknown)

                HWIN_EXPORT ImageEncoder& WriteFrame( ID2D1Image *pImage, const BitmapFrameEncode& theFrameEncoder, const ImageParameters& theImageParameters);
                HWIN_EXPORT ImageEncoder& WriteFrameThumbnail( ID2D1Image *pImage, const BitmapFrameEncode& theFrameEncoder, const ImageParameters& theImageParameters);
                HWIN_EXPORT ImageEncoder& WriteThumbnail( ID2D1Image *pImage, const BitmapEncoder& theEncoder, const ImageParameters& theImageParameters);
            };



            class BitmapDecoderInfo;
            class BitmapFrameDecode;
            class BitmapDecoder : public ImagingObject
            {
            public:
                typedef ImagingObject Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(BitmapDecoder,ImagingObject,IWICBitmapDecoder,IUnknown)

                HWIN_EXPORT DWORD QueryCapability( IStream * theStream) const;
        
                HWIN_EXPORT BitmapDecoder& Initialize( IStream* theStream, DecodeOptions cacheOptions);
        
                HWIN_EXPORT const BitmapDecoder& GetContainerFormat(GUID *pguidContainerFormat) const;
                HWIN_EXPORT GUID GetContainerFormat( ) const;
        
                HWIN_EXPORT BitmapDecoderInfo GetDecoderInfo( ) const;
        
                HWIN_EXPORT const BitmapDecoder& CopyPalette( Palette& theTargetPalette ) const;
                HWIN_EXPORT Palette CopyPalette( ) const;
        
                HWIN_EXPORT MetadataQueryReader GetMetadataQueryReader( ) const;
        
                HWIN_EXPORT BitmapSource GetPreview( ) const;
        
                HWIN_EXPORT std::shared_ptr< std::vector<ColorContext> >  GetColorContexts( ) const;
        
                HWIN_EXPORT BitmapSource GetThumbnail( ) const;
        
                HWIN_EXPORT UINT GetFrameCount( ) const;
        
                HWIN_EXPORT BitmapFrameDecode GetFrame(UINT index) const;
        
            };


            class BitmapSourceTransform : public ImagingObject
            {
            public:
                typedef ImagingObject Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(BitmapSourceTransform,ImagingObject,IWICBitmapSourceTransform,IUnknown)

                HWIN_EXPORT const BitmapSourceTransform& CopyPixels( const Rectangle& rectangle, UINT uiWidth, UINT uiHeight, WICPixelFormatGUID *pguidDstFormat,BitmapTransformOptions dstTransform,UINT nStride,UINT cbBufferSize,BYTE *pbBuffer) const;
        
                HWIN_EXPORT const BitmapSourceTransform& GetClosestSize( UINT *puiWidth,UINT *puiHeight) const;
        
                HWIN_EXPORT const BitmapSourceTransform& GetClosestPixelFormat( WICPixelFormatGUID *pguidDstFormat) const;
        
                HWIN_EXPORT bool DoesSupportTransform( BitmapTransformOptions dstTransform) const;
        
            };


            class BitmapFrameDecode : public BitmapSource
            {
            public:
                typedef BitmapSource Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(BitmapFrameDecode,BitmapSource,IWICBitmapFrameDecode,IWICBitmapSource)

                HWIN_EXPORT MetadataQueryReader GetMetadataQueryReader( ) const;
        
                HWIN_EXPORT std::shared_ptr< std::vector<ColorContext> > GetColorContexts( ) const;
        
                HWIN_EXPORT BitmapSource GetThumbnail( ) const;
        
            };

            class ProgressiveLevelControl : public ImagingObject
            {
            public:
                typedef ImagingObject Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(ProgressiveLevelControl,ImagingObject,IWICProgressiveLevelControl,IUnknown)

                HWIN_EXPORT UINT GetLevelCount( );
                HWIN_EXPORT UINT GetCurrentLevel( );
                HWIN_EXPORT ProgressiveLevelControl& SetCurrentLevel( UINT theLevel);
        
            };


            class ProgressCallback : public IUnknownImplementation<IWICProgressCallback>
            {
            public:
                typedef IUnknownImplementation<IWICProgressCallback> Base;
                HWIN_EXPORT virtual HRESULT STDMETHODCALLTYPE Notify( ULONG uFrameNum, WICProgressOperation operation, double dblProgress);
            };


            class BitmapCodecProgressNotification : public ImagingObject
            {
            public:
                typedef ImagingObject Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(BitmapCodecProgressNotification,ImagingObject,IWICBitmapCodecProgressNotification,IUnknown)

                HWIN_EXPORT BitmapCodecProgressNotification& RegisterProgressNotification( PFNProgressNotification pfnProgressNotification, LPVOID pvData,DWORD dwProgressFlags);
        
            };


            class ComponentInfo : public ImagingObject
            {
            public:
                typedef ImagingObject Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(ComponentInfo,ImagingObject,IWICComponentInfo,IUnknown)

                HWIN_EXPORT ComponentType GetComponentType( ) const;
        
                HWIN_EXPORT const ComponentInfo& GetCLSID( CLSID *pclsid) const;
                HWIN_EXPORT CLSID GetCLSID( ) const;
        
                HWIN_EXPORT DWORD GetSigningStatus( ) const;
        
                HWIN_EXPORT String GetAuthor( ) const;
        
                HWIN_EXPORT const ComponentInfo& GetVendorGUID(GUID *pguidVendor) const;
                HWIN_EXPORT GUID GetVendorGUID( ) const;
        
                HWIN_EXPORT String GetVersion( ) const;
        
                HWIN_EXPORT String GetSpecVersion( ) const;
        
                HWIN_EXPORT String GetFriendlyName( ) const;
        
            };

            class FormatConverter;
            class FormatConverterInfo : public ComponentInfo
            {
            public:
                typedef ComponentInfo Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(FormatConverterInfo,ComponentInfo,IWICFormatConverterInfo,IWICComponentInfo)

                HWIN_EXPORT std::shared_ptr< std::vector<WICPixelFormatGUID> > GetPixelFormats( ) const;
                HWIN_EXPORT FormatConverter CreateInstance( ) const;
        
            };


            class BitmapCodecInfo : public ComponentInfo
            {
            public:
                typedef ComponentInfo Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(BitmapCodecInfo,ComponentInfo,IWICBitmapCodecInfo,IWICComponentInfo)

                HWIN_EXPORT const BitmapCodecInfo& GetContainerFormat(GUID *pguidContainerFormat) const;
                HWIN_EXPORT GUID GetContainerFormat( ) const;
        
                HWIN_EXPORT std::shared_ptr< std::vector<WICPixelFormatGUID> > GetPixelFormats( ) const;
        
                HWIN_EXPORT String GetColorManagementVersion( ) const;
        
                HWIN_EXPORT String GetDeviceManufacturer( ) const;
        
                HWIN_EXPORT String GetDeviceModels( ) const;
        
                HWIN_EXPORT String GetMimeTypes( ) const;
        
                HWIN_EXPORT String GetFileExtensions( ) const;
        
                HWIN_EXPORT bool DoesSupportAnimation() const;
        
                HWIN_EXPORT bool DoesSupportChromakey( ) const;
        
                HWIN_EXPORT bool DoesSupportLossless( ) const;
        
                HWIN_EXPORT bool DoesSupportMultiframe( ) const;
        
                HWIN_EXPORT bool MatchesMimeType(LPCWSTR wzMimeType) const;
                HWIN_EXPORT bool MatchesMimeType(const String& theMimeType) const;
        
            };


            class BitmapEncoderInfo : public BitmapCodecInfo
            {
            public:
                typedef BitmapCodecInfo Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(BitmapEncoderInfo,BitmapCodecInfo,IWICBitmapEncoderInfo,IWICBitmapCodecInfo)

                HWIN_EXPORT BitmapEncoder CreateInstance( );
        
            };


            class BitmapDecoderInfo : public BitmapCodecInfo
            {
            public:
                typedef BitmapCodecInfo Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(BitmapDecoderInfo,BitmapCodecInfo,IWICBitmapDecoderInfo,IWICBitmapCodecInfo)

                HWIN_EXPORT std::shared_ptr< std::vector<BitmapPattern> > GetPatterns( ) const;
        
                HWIN_EXPORT bool MatchesPattern( IStream *theStream) const;
        
                HWIN_EXPORT BitmapDecoder CreateInstance( ) const;
        
            };


            class PixelFormatInfo : public ComponentInfo
            {
            public:
                typedef ComponentInfo Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(PixelFormatInfo,ComponentInfo,IWICPixelFormatInfo,IWICComponentInfo)

                HWIN_EXPORT const PixelFormatInfo& GetFormatGUID(GUID *pFormat) const;
        
                HWIN_EXPORT ColorContext GetColorContext( ) const;
        
                HWIN_EXPORT UINT GetBitsPerPixel( ) const;
        
                HWIN_EXPORT UINT GetChannelCount( ) const;
        
                HWIN_EXPORT std::shared_ptr< std::vector<BYTE> > GetChannelMask( UINT uiChannelIndex ) const;

                // IWICPixelFormatInfo2
                //HWIN_EXPORT bool SupportsTransparency( ) const;
        
                //HWIN_EXPORT PixelFormatNumericRepresentation GetNumericRepresentation( ) const;
        
            };


            class ImagingFactory : public ImagingObject
            {
            public:
                typedef ImagingObject Base;
                HARLINN_WINDOWS_IMAGING_STANDARD_METHODS_IMPL(ImagingFactory,ImagingObject,IWICImagingFactory,IUnknown)

                HWIN_EXPORT static ImagingFactory Create();

                HWIN_EXPORT BitmapDecoder CreateDecoderFromFilename( LPCWSTR theFilename,const GUID *pguidVendor, DWORD dwDesiredAccess, DecodeOptions metadataOptions) const;
                HWIN_EXPORT BitmapDecoder CreateDecoderFromFilename( LPCWSTR theFilename, DWORD dwDesiredAccess, DecodeOptions metadataOptions) const;
                HWIN_EXPORT BitmapDecoder CreateDecoderFromFilename( LPCWSTR theFilename ) const;

                HWIN_EXPORT BitmapDecoder CreateDecoderFromFilename( const String& theFilename,const GUID *pguidVendor, DWORD dwDesiredAccess, DecodeOptions metadataOptions) const;
                HWIN_EXPORT BitmapDecoder CreateDecoderFromFilename( const String& theFilename, DWORD dwDesiredAccess, DecodeOptions metadataOptions) const;
                HWIN_EXPORT BitmapDecoder CreateDecoderFromFilename( const String& theFilename ) const;

        
                HWIN_EXPORT BitmapDecoder CreateDecoderFromStream( IStream *theStream, const GUID *pguidVendor, DecodeOptions metadataOptions) const;
                HWIN_EXPORT BitmapDecoder CreateDecoderFromStream( IStream *theStream, DecodeOptions metadataOptions) const;
        
                HWIN_EXPORT BitmapDecoder CreateDecoderFromFileHandle(ULONG_PTR hFile, const GUID *pguidVendor, DecodeOptions metadataOptions) const;
        
                HWIN_EXPORT ComponentInfo CreateComponentInfo( REFCLSID clsidComponent) const;
        
                HWIN_EXPORT BitmapDecoder CreateDecoder( REFGUID guidContainerFormat, const GUID *pguidVendor) const;
        
                HWIN_EXPORT BitmapEncoder CreateEncoder( REFGUID guidContainerFormat,const GUID *pguidVendor) const;

                HWIN_EXPORT BitmapEncoder CreateBMPEncoder( ) const;
                HWIN_EXPORT BitmapEncoder CreatePNGEncoder( ) const;
                HWIN_EXPORT BitmapEncoder CreateICOEncoder( ) const;
                HWIN_EXPORT BitmapEncoder CreateJPEGEncoder( ) const;
                HWIN_EXPORT BitmapEncoder CreateTIFFEncoder( ) const;
                HWIN_EXPORT BitmapEncoder CreateGIFEncoder( ) const;
                HWIN_EXPORT BitmapEncoder CreateWMPEncoder( ) const;

        
                HWIN_EXPORT Palette CreatePalette( ) const;
        
                HWIN_EXPORT FormatConverter CreateFormatConverter( ) const;
        
                HWIN_EXPORT BitmapScaler CreateBitmapScaler( ) const;
        
                HWIN_EXPORT BitmapClipper CreateBitmapClipper( ) const;
        
                HWIN_EXPORT BitmapFlipRotator CreateBitmapFlipRotator( ) const;
        
                HWIN_EXPORT Stream CreateStream( ) const;
        
                HWIN_EXPORT ColorContext CreateColorContext( ) const;
        
                HWIN_EXPORT ColorTransform CreateColorTransformer( ) const;
        
                HWIN_EXPORT Bitmap CreateBitmap( UINT uiWidth,UINT uiHeight,REFWICPixelFormatGUID pixelFormat, BitmapCreateCacheOption option) const;
        
                HWIN_EXPORT Bitmap CreateBitmapFromSource( const BitmapSource& theBitmapSource,BitmapCreateCacheOption option) const;
        
                HWIN_EXPORT Bitmap CreateBitmapFromSourceRect( const BitmapSource& theBitmapSource,UINT x,UINT y,UINT width,UINT height) const;
        
                HWIN_EXPORT Bitmap CreateBitmapFromMemory( UINT uiWidth,UINT uiHeight,REFWICPixelFormatGUID pixelFormat,UINT cbStride,UINT cbBufferSize,BYTE *pbBuffer) const;
        
                HWIN_EXPORT Bitmap CreateBitmapFromHBITMAP( HBITMAP hBitmap, HPALETTE hPalette, BitmapAlphaChannelOption options) const;
        
                HWIN_EXPORT Bitmap CreateBitmapFromHICON(HICON hIcon) const;
        
                HWIN_EXPORT const ImagingFactory& CreateComponentEnumerator( DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown) const;
        
                HWIN_EXPORT FastMetadataEncoder CreateFastMetadataEncoderFromDecoder( const BitmapDecoder& theDecoder) const;
        
                HWIN_EXPORT FastMetadataEncoder CreateFastMetadataEncoderFromFrameDecode(const BitmapFrameDecode& theFrameDecoder) const;
        
                HWIN_EXPORT MetadataQueryWriter CreateQueryWriter( REFGUID guidMetadataFormat, const GUID *pguidVendor) const;
        
                HWIN_EXPORT MetadataQueryWriter CreateQueryWriterFromReader( const MetadataQueryReader& theQueryReader, const GUID *pguidVendor) const;
        
            };






        };
    };
};

#endif //__HWINIMAGING_H__

